package cn.sciento.boot.api.customize.helper.impl;

import java.util.Map;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import cn.sciento.boot.api.customize.helper.HttpRequestHelper;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

public class DefaultHttpRequestHelper implements HttpRequestHelper {
  private volatile RestTemplate restTemplate;
  
  private HttpHeaders headers;
  
  @PostConstruct
  public void init() {
    initRestTemplate();
    this.headers = new HttpHeaders();
    this.headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
  }
  
  public ResponseEntity request(String url, HttpMethod method, Map<String, Object> params) {
    initRestTemplate();
    Object[] uriArgs = getUriArgs(url, params);
    return this.restTemplate.exchange(url, method, getHttpEntity(method, params), Object.class, uriArgs);
  }
  
  private HttpEntity getHttpEntity(HttpMethod method, Map<String, Object> params) {
    if (HttpMethod.GET.equals(method))
      return null; 
    return new HttpEntity(params, (MultiValueMap)this.headers);
  }
  
  private void initRestTemplate() {
    if (this.restTemplate == null)
      synchronized (this) {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectTimeout(120000);
        httpRequestFactory.setReadTimeout(300000);
        this.restTemplate = new RestTemplate((ClientHttpRequestFactory)httpRequestFactory);
      }  
  }
  
  private Object[] getUriArgs(String url, Map<String, Object> params) {
    Object[] uriArgs = ArrayUtils.EMPTY_OBJECT_ARRAY;
    if (StringUtils.containsAny(url, new CharSequence[] { "{", "}" })) {
      String[] uriArgNames = StringUtils.substringsBetween(url, "{", "}");
      uriArgs = new Object[uriArgNames.length];
      for (int i = 0; i < uriArgNames.length; i++)
        uriArgs[i] = params.get(uriArgNames[i]); 
    } 
    return uriArgs;
  }
}
